package org.example;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author shenguangyang
 */
@Component
public class ZookeeperApiImpl implements ZookeeperApi {
    private static final Logger log = LoggerFactory.getLogger(ZookeeperApiImpl.class);
    @Resource
    private ZooKeeper zkClient;

    @Override
    public Stat exists(String path, boolean needWatch) {
        try {
            return zkClient.exists(path, needWatch);
        } catch (Exception e) {
            log.error("exist path {}, error: ", path, e);
            return null;
        }
    }

    @Override
    public Stat exists(String path, Watcher watcher) {
        try {
            return zkClient.exists(path, watcher);
        } catch (Exception e) {
            log.error("exist path {}, error: ", path, e);
            return null;
        }
    }

    @Override
    public boolean createNode(String path, String data, CreateMode createMode) {
        try {
            zkClient.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
            return true;
        } catch (Exception e) {
            log.error("create node fail, path: {}, data: {}, error: ", path, data, e);
            return false;
        }
    }

    @Override
    public boolean updateNode(String path, String data) {
        try {
            // zk的数据版本是从0开始计数的。如果客户端传入的是-1，则表示zk服务器需要基于最新的数据进行更新。
            // 如果对zk的数据节点的更新操作没有原子性要求则可以使用-1.

            // version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
            zkClient.setData(path, data.getBytes(), -1);
            return true;
        } catch (Exception e) {
            log.error("update node fail, path: {}, data: {}, error: ", path, data, e);
            return false;
        }
    }

    @Override
    public boolean deleteNode(String path) {
        try {
            // version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
            zkClient.delete(path, -1);
            return true;
        } catch (Exception e) {
            log.error("delete node fail, path: {}, error: ", path, e);
            return false;
        }
    }

    @Override
    public List<String> getChildren(String path) throws KeeperException, InterruptedException {
        return zkClient.getChildren(path, false);
    }

    @Override
    public String getData(String path, Watcher watcher) throws InterruptedException, KeeperException {
        try {
            Stat stat = new Stat();
            byte[] bytes = zkClient.getData(path, watcher, stat);
            return new String(bytes);
        } catch (Exception e) {
            throw e;
        }
    }
}
